package com.frame.sulent.datasource.common;

import java.util.HashMap;
import java.util.Map;

public class DataTypeMapper {

    private static final Map<String, Integer> MysqlDataTypeMap = new HashMap<>();
    private static final Map<String, Integer> PostgresqlDataTypeMap = new HashMap<>();
    private static final Map<String, Integer> OracleDataTypeMap = new HashMap<>();

    static {
        //MYSQL
        // Numeric types
        MysqlDataTypeMap.put("int", CommonConstant.LogicalDataType.NUMERIC);
        MysqlDataTypeMap.put("tinyint", CommonConstant.LogicalDataType.NUMERIC);
        MysqlDataTypeMap.put("smallint", CommonConstant.LogicalDataType.NUMERIC);
        MysqlDataTypeMap.put("mediumint", CommonConstant.LogicalDataType.NUMERIC);
        MysqlDataTypeMap.put("bigint", CommonConstant.LogicalDataType.NUMERIC);
        MysqlDataTypeMap.put("float", CommonConstant.LogicalDataType.NUMERIC);
        MysqlDataTypeMap.put("double", CommonConstant.LogicalDataType.NUMERIC);
        MysqlDataTypeMap.put("decimal", CommonConstant.LogicalDataType.NUMERIC);
        MysqlDataTypeMap.put("numeric", CommonConstant.LogicalDataType.NUMERIC);
        // Character types
        MysqlDataTypeMap.put("char", CommonConstant.LogicalDataType.CHARACTER_STR);
        MysqlDataTypeMap.put("varchar", CommonConstant.LogicalDataType.CHARACTER_STR);
        MysqlDataTypeMap.put("text", CommonConstant.LogicalDataType.CHARACTER_STR);
        MysqlDataTypeMap.put("tinytext", CommonConstant.LogicalDataType.CHARACTER_STR);
        MysqlDataTypeMap.put("mediumtext", CommonConstant.LogicalDataType.CHARACTER_STR);
        MysqlDataTypeMap.put("longtext", CommonConstant.LogicalDataType.CHARACTER_STR);
        // Date and time types
        MysqlDataTypeMap.put("date", CommonConstant.LogicalDataType.DATE_TIME);
        MysqlDataTypeMap.put("datetime", CommonConstant.LogicalDataType.DATE_TIME);
        MysqlDataTypeMap.put("timestamp", CommonConstant.LogicalDataType.DATE_TIME);
        MysqlDataTypeMap.put("time", CommonConstant.LogicalDataType.DATE_TIME);
        MysqlDataTypeMap.put("year", CommonConstant.LogicalDataType.DATE_TIME);
        // Boolean type
        MysqlDataTypeMap.put("boolean", CommonConstant.LogicalDataType.BOOLEAN);
        MysqlDataTypeMap.put("bit", CommonConstant.LogicalDataType.BOOLEAN);
        // Binary types
        MysqlDataTypeMap.put("binary", CommonConstant.LogicalDataType.BINARY);
        MysqlDataTypeMap.put("varbinary", CommonConstant.LogicalDataType.BINARY);
        MysqlDataTypeMap.put("blob", CommonConstant.LogicalDataType.BINARY);
        MysqlDataTypeMap.put("tinyblob", CommonConstant.LogicalDataType.BINARY);
        MysqlDataTypeMap.put("mediumblob", CommonConstant.LogicalDataType.BINARY);
        MysqlDataTypeMap.put("longblob", CommonConstant.LogicalDataType.BINARY);
        // Other types (if any)
        MysqlDataTypeMap.put("enum", CommonConstant.LogicalDataType.OTHER);
        MysqlDataTypeMap.put("set", CommonConstant.LogicalDataType.OTHER);
        // Add other types as needed...

        //POSTGRESQL
        //NUMERIC
        PostgresqlDataTypeMap.put("smallint", CommonConstant.LogicalDataType.NUMERIC);
        PostgresqlDataTypeMap.put("integer", CommonConstant.LogicalDataType.NUMERIC);
        PostgresqlDataTypeMap.put("bigint", CommonConstant.LogicalDataType.NUMERIC);
        PostgresqlDataTypeMap.put("decimal", CommonConstant.LogicalDataType.NUMERIC);
        PostgresqlDataTypeMap.put("numeric", CommonConstant.LogicalDataType.NUMERIC);
        PostgresqlDataTypeMap.put("real", CommonConstant.LogicalDataType.NUMERIC);
        PostgresqlDataTypeMap.put("double precision", CommonConstant.LogicalDataType.NUMERIC);
        PostgresqlDataTypeMap.put("smallserial", CommonConstant.LogicalDataType.NUMERIC);
        PostgresqlDataTypeMap.put("serial", CommonConstant.LogicalDataType.NUMERIC);
        PostgresqlDataTypeMap.put("bigserial", CommonConstant.LogicalDataType.NUMERIC);
        //CHARACTER_STR
        PostgresqlDataTypeMap.put("char", CommonConstant.LogicalDataType.CHARACTER_STR);
        PostgresqlDataTypeMap.put("character", CommonConstant.LogicalDataType.CHARACTER_STR);
        PostgresqlDataTypeMap.put("varchar", CommonConstant.LogicalDataType.CHARACTER_STR);
        PostgresqlDataTypeMap.put("character varying", CommonConstant.LogicalDataType.CHARACTER_STR);
        PostgresqlDataTypeMap.put("text", CommonConstant.LogicalDataType.CHARACTER_STR);
        PostgresqlDataTypeMap.put("citext", CommonConstant.LogicalDataType.CHARACTER_STR);
        //DATE_TIME
        PostgresqlDataTypeMap.put("date", CommonConstant.LogicalDataType.DATE_TIME);
        PostgresqlDataTypeMap.put("time", CommonConstant.LogicalDataType.DATE_TIME);
        PostgresqlDataTypeMap.put("timestamp", CommonConstant.LogicalDataType.DATE_TIME);
        PostgresqlDataTypeMap.put("timestamptz", CommonConstant.LogicalDataType.DATE_TIME);
        PostgresqlDataTypeMap.put("interval", CommonConstant.LogicalDataType.DATE_TIME);
        //BOOLEAN
        PostgresqlDataTypeMap.put("boolean", CommonConstant.LogicalDataType.BOOLEAN);
        //BINARY
        PostgresqlDataTypeMap.put("bytea", CommonConstant.LogicalDataType.BINARY);
        //OTHER
        PostgresqlDataTypeMap.put("uuid", CommonConstant.LogicalDataType.OTHER);
        PostgresqlDataTypeMap.put("xml", CommonConstant.LogicalDataType.OTHER);
        PostgresqlDataTypeMap.put("array", CommonConstant.LogicalDataType.OTHER);
        PostgresqlDataTypeMap.put("range", CommonConstant.LogicalDataType.OTHER);
        PostgresqlDataTypeMap.put("json", CommonConstant.LogicalDataType.OTHER);
        PostgresqlDataTypeMap.put("jsonb", CommonConstant.LogicalDataType.OTHER);
        PostgresqlDataTypeMap.put("money", CommonConstant.LogicalDataType.OTHER);
        PostgresqlDataTypeMap.put("cidr", CommonConstant.LogicalDataType.OTHER);
        PostgresqlDataTypeMap.put("inet", CommonConstant.LogicalDataType.OTHER);
        PostgresqlDataTypeMap.put("xid", CommonConstant.LogicalDataType.OTHER);
        PostgresqlDataTypeMap.put("cid", CommonConstant.LogicalDataType.OTHER);
        PostgresqlDataTypeMap.put("oid", CommonConstant.LogicalDataType.OTHER);

        PostgresqlDataTypeMap.put("point", CommonConstant.LogicalDataType.OTHER);
        PostgresqlDataTypeMap.put("line", CommonConstant.LogicalDataType.OTHER);
        PostgresqlDataTypeMap.put("lseg", CommonConstant.LogicalDataType.OTHER);
        PostgresqlDataTypeMap.put("box", CommonConstant.LogicalDataType.OTHER);
        PostgresqlDataTypeMap.put("path", CommonConstant.LogicalDataType.OTHER);
        PostgresqlDataTypeMap.put("polygon", CommonConstant.LogicalDataType.OTHER);
        PostgresqlDataTypeMap.put("circle", CommonConstant.LogicalDataType.OTHER);
        //...

        //ORACLE
        OracleDataTypeMap.put("number", CommonConstant.LogicalDataType.NUMERIC);
        OracleDataTypeMap.put("float", CommonConstant.LogicalDataType.NUMERIC);
        OracleDataTypeMap.put("binary_float", CommonConstant.LogicalDataType.NUMERIC);
        OracleDataTypeMap.put("binary_double", CommonConstant.LogicalDataType.NUMERIC);

        OracleDataTypeMap.put("char", CommonConstant.LogicalDataType.CHARACTER_STR);
        OracleDataTypeMap.put("varchar2", CommonConstant.LogicalDataType.CHARACTER_STR);
        OracleDataTypeMap.put("nvarchar2", CommonConstant.LogicalDataType.CHARACTER_STR);
        OracleDataTypeMap.put("clob", CommonConstant.LogicalDataType.CHARACTER_STR);
        OracleDataTypeMap.put("nclob", CommonConstant.LogicalDataType.CHARACTER_STR);

        OracleDataTypeMap.put("date", CommonConstant.LogicalDataType.DATE_TIME);
        OracleDataTypeMap.put("timestamp", CommonConstant.LogicalDataType.DATE_TIME);
        OracleDataTypeMap.put("timestamp with time zone", CommonConstant.LogicalDataType.DATE_TIME);
        OracleDataTypeMap.put("timestamp with local time zone", CommonConstant.LogicalDataType.DATE_TIME);

        OracleDataTypeMap.put("boolean", CommonConstant.LogicalDataType.BOOLEAN);

        OracleDataTypeMap.put("blob", CommonConstant.LogicalDataType.BINARY);
        OracleDataTypeMap.put("bfile", CommonConstant.LogicalDataType.BINARY);

        OracleDataTypeMap.put("rowid", CommonConstant.LogicalDataType.OTHER);
        OracleDataTypeMap.put("urowid", CommonConstant.LogicalDataType.OTHER);

    }

    public static Integer getLogicalType(String dbType,String physicalType) {
        switch (dbType.toLowerCase()){
            case "mysql":
                return MysqlDataTypeMap.getOrDefault(physicalType.toLowerCase(), CommonConstant.LogicalDataType.OTHER);
            case "postgresql":
                return PostgresqlDataTypeMap.getOrDefault(physicalType.toLowerCase(), CommonConstant.LogicalDataType.OTHER);
            case "oracle":
                return OracleDataTypeMap.getOrDefault(physicalType.toLowerCase(), CommonConstant.LogicalDataType.OTHER);
            default:
                return CommonConstant.LogicalDataType.OTHER;
        }
    }
}